package be.kuleuven.cs.mop.gui.dialogs;


import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import be.kuleuven.cs.mop.app.controllers.Controllers;
import be.kuleuven.cs.mop.domain.exceptions.InvalidCurrentUserException;
import be.kuleuven.cs.mop.domain.model.Task;
import be.kuleuven.cs.mop.domain.model.impl.Field;
import be.kuleuven.cs.mop.gui.components.ActionButton;
import be.kuleuven.cs.mop.gui.components.ComboSelector;
import be.kuleuven.cs.mop.gui.components.InfoLabel;
import be.kuleuven.cs.mop.gui.components.ScheduleInput;
import be.kuleuven.cs.mop.gui.components.SelectionList;
import be.kuleuven.cs.mop.gui.components.TaskFieldsInput;
import be.kuleuven.cs.mop.gui.components.Wrapper;
import be.kuleuven.cs.mop.gui.util.SwingUtils;
import be.kuleuven.cs.mop.util.Utils;



/**
 * {@link ActionDialog} for the "Modify Task Details" use case
 */
public class ModifyTaskDialog extends DynamicActionDialog<Task> {
	private static final long serialVersionUID = 1L;
	
	private SelectionList<Task>			dependencies;
	private Wrapper<TaskFieldsInput>	fields			=
		new Wrapper<TaskFieldsInput>();
	private Wrapper<InfoLabel>			info			= new Wrapper<InfoLabel>();
	private ScheduleInput				schedule		= new ScheduleInput();
	private ComboSelector<Task>			tasks;
	
	
	public ModifyTaskDialog(final Frame parent, final Controllers controllers,
			final Task task) {
		super(parent, "Modify Task Details", controllers);
		final GridBagConstraints gbc = SwingUtils.getGBC();
		
		try {
			final List<Task> tasks =
				getControllers().getControllerTasks().getUserTasks();
			
			this.dependencies = new SelectionList<Task>(tasks, true);
			if (task == null) {
				this.tasks	=
					new ComboSelector<Task>(tasks.toArray(new Task[tasks.size()]));
			} else {
				this.tasks = new ComboSelector<Task>(new Task[] { task });
			}
		} catch (final InvalidCurrentUserException e) {
			log(e);
			dispose();
			return;
		}
		
		try {
			update(getSelection());
		} catch (final Exception e) {
			//	ignored
		}
		
		gbc.insets	= new Insets(5, 5, 5, 5);
		
		tasks.addActionListener(new UpdateListener());
		gbc.gridx	= 0;
		gbc.gridy	= 0;
		add(tasks, gbc);
		
		gbc.gridy	= 1;
		add(schedule, gbc);
		
		gbc.gridy	= 2;
		add(new ActionButton("Modify", new Dimension(150, 32), this), gbc);
		
		info.setPreferredSize(new Dimension(400, 500));
		gbc.gridx	= 1;
		gbc.gridy	= 0;
		gbc.gridheight	= 4;
		add(info, gbc);
		
		gbc.gridx	= 3;
		gbc.gridheight	= 3;
		add(fields, gbc);
		
		gbc.gridy	= 3;
		gbc.gridheight	= 1;
		add(dependencies.wrap(new Dimension(400, 250)), gbc);
		
		display();
	}
	
	
	
	@Override
	protected Task getSelection() {
		return tasks.getSelection();
	}
	
	@Override
	protected void handle(final ActionEvent event) throws Exception {
		final Task task = tasks.getSelection();
		if (task == null) {
			log("Please select a Task");
			return;
		}
		
		getControllers().getControllerTasks().modifyTask(task,
				schedule.read(),
				new HashSet<Task>(dependencies.getSelection()),
				new HashMap<String, Field>(fields.get().read()));
		log("Modified '%s'", task);
		dispose();
	}
	
	@Override
	protected void update(final Task selection) throws Exception {
		dependencies.setSelection(new ArrayList<Task>(selection.getDependencies()));
		fields.set(new TaskFieldsInput(selection));
		info.set(new InfoLabel(Utils.format(selection, false)));
		schedule.write(selection.getSchedule());
	}
	
}